package com.tianji.learning.task;

import cn.hutool.db.meta.Table;
import com.tianji.common.utils.CollUtils;
import com.tianji.common.utils.DateUtils;
import com.tianji.learning.constans.RedisConstants;
import com.tianji.learning.domain.po.PointsBoard;
import com.tianji.learning.domain.po.PointsBoardSeason;
import com.tianji.learning.service.IPointsBoardSeasonService;
import com.tianji.learning.service.IPointsBoardService;
import com.tianji.learning.utils.TableInfoContext;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

import static com.tianji.learning.constans.LearningConstants.POINTS_BOARD_TABLE_PREFIX;

@Component
@RequiredArgsConstructor
@Slf4j
public class PointsBoardPersistentHandler {

    private final IPointsBoardSeasonService pointsBoardSeasonService;

    private final RedisTemplate redisTemplate;

    private final IPointsBoardService pointsBoardService;

//  @Scheduled(cron = "0 0 3 1 * ?") // 每月1号凌晨三点
    @XxlJob("createTableJob")
    public void createPointsBoardTableOfLastSeason(){
        log.debug("执行建表操作（学霸榜）");
        // 1. 获取上月当前时间点
        LocalDateTime time = LocalDateTime.now().minusMonths(1);

        // 2. 查询赛季表获取赛级id
        PointsBoardSeason one = pointsBoardSeasonService.lambdaQuery()
                .le(PointsBoardSeason::getBeginTime, time)
                .ge(PointsBoardSeason::getBeginTime, time)
                .one();
        if(one == null){
            return ;
        }
        // 3. 创建赛季榜单
        pointsBoardSeasonService.createPointBoardLatestSession(one.getId());
    }

    @XxlJob("savePointsBoard2DB")
    public void savePointsBoard2Database(){
        int shardIndex = XxlJobHelper.getShardIndex();
        int shardTotal = XxlJobHelper.getShardTotal();

        // 1. 获取上月当前时间点
        LocalDateTime time = LocalDateTime.now().minusMonths(1);
        // 2. 查询赛季表points_board_season 获取上赛季信息
        PointsBoardSeason one = pointsBoardSeasonService.lambdaQuery()
                .le(PointsBoardSeason::getBeginTime, time)
                .ge(PointsBoardSeason::getBeginTime, time)
                .one();
        if(one == null){
            return ;
        }

        // 3. 动态计算表名字， 存储在threadlocal中
        String tableName = POINTS_BOARD_TABLE_PREFIX + one.getId();
        TableInfoContext.setInfo(tableName);
        log.debug("获取动态表名{}", tableName);
        // 4. 分页获取redis上赛季积分排行榜单
        String format = time.format(DateTimeFormatter.ofPattern("yyyyMM"));
        String key = RedisConstants.POINTS_BOARD_KEY_PREFIX+format;
        while(true){
            int pageNo = 1 + shardIndex;
            int pageSize = 1000;
            List<PointsBoard> pointsBoardList = pointsBoardService.queryMyCurrentBoard(key, pageSize, pageNo);
            if(CollUtils.isEmpty(pointsBoardList)){
                break;
            }
            pageNo += shardTotal;
            // 持久化到db响应的赛季表中 批量更新
            for(PointsBoard board: pointsBoardList){
                board.setId(Long.valueOf(board.getRank())); //在历史赛季表中，就代表了排名
                board.setRank(null);
            }
            pointsBoardService.saveBatch(pointsBoardList);
        }
        // 删除表明
        TableInfoContext.remove();
    }

    @XxlJob("clearPointsBoardFromRedis")
    public void clearPointFromRedis(){
        //1. 获取上月时间
        LocalDateTime time = LocalDateTime.now().minusMonths(1);
        // 2. 计算key
        String key = RedisConstants.POINTS_BOARD_KEY_PREFIX+time.format(DateUtils.SIGN_DATE_SUFFIX_FORMATTER);
        // 3. 删除
        redisTemplate.unlink(key);
    }




}
